package mymvc.util
{
	/**
	 * 
	 * 类加载器
	 * 
	 * 
	 */ 
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import mymvc.event.ClassLoadCompleteEvent;
	
	public class ClassLoader extends Loader implements IEventDispatcher
	{
		public var classLoaderInfo:ClassLoaderInfo = null;
		public var dispatcher:EventDispatcher = null;
		private var classArray:Array = null;
		public function ClassLoader()
		{
			super();
			dispatcher = new EventDispatcher();
			initLoadEvent(contentLoaderInfo);
			classArray = new Array();
		}
		
		public function loadClass(request:String,className:String, context:LoaderContext = null):void{
			contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
			var classLoader:ClassLoader = this;
			function onComplete(event:Event):void{
				classLoader.dispatchEvent(new ClassLoadCompleteEvent(ClassLoadCompleteEvent.CLASS_LOAD_COMPLETE,className,
					classLoader.getClassDefinition(className,contentLoaderInfo)));
			}
			super.load(new URLRequest(request),context);
		}
		
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
		{
			dispatcher.addEventListener(type,listener,useCapture);
		}
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
		{
			dispatcher.removeEventListener(type,listener,useCapture);
		}
		
		override public function dispatchEvent(event:Event):Boolean
		{
			return dispatcher.dispatchEvent(event);
		}
		
		override public function hasEventListener(type:String):Boolean
		{
			return false;
		}
		
		override public function willTrigger(type:String):Boolean
		{
			return false;
		}
		
		/**
		 * 获取当前ApplicationDomain内的类定义
		 * 
		 * name类名称，必须包含完整的命名空间,如 Grave.Function.SWFLoader
		 * info加载swf的LoadInfo，不指定则从当前域获取
		 * return获取的类定义，如果不存在返回null
		 */
		private function getClassDefinition(name:String, info:LoaderInfo):Class 
		{
			try 
			{
				if (info == null) 
				{
					return ApplicationDomain.currentDomain.getDefinition(name) as Class;
				}
				return info.applicationDomain.getDefinition(name) as Class;
			} 
			catch (e:ReferenceError) 
			{
				trace("定义 " + name + " 不存在");
				return null;
			}
			return null;
		}
		
		public function getClass(className:String):Class{
			var result:Class = null;
			for(var i:int = 0;i<classArray.length;i++){
				if(classArray[i].hasOwnProperty(className)){
					result = classArray[i][className] as Class;
					break;
				}
			}
			return result;
		}
		/**
		 * @private
		 * 监听加载事件
		 * 
		 * @param info加载对象的LoaderInfo
		 */
		private function initLoadEvent(info : LoaderInfo):void 
		{
			info.addEventListener(ProgressEvent.PROGRESS, this.onProgress);
			//info.addEventListener(Event.COMPLETE, this.onComplete);
			
			
			info.addEventListener(IOErrorEvent.IO_ERROR, this.onError);
			info.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.onError);
		}
		
		/**
		 * @private
		 * 移除加载事件
		 * 
		 * @param inft加载对象的LoaderInfo
		 */
		private function RemoveLoadEvent(info:LoaderInfo):void 
		{
			//info.removeEventListener(Event.COMPLETE,onComplete);
			info.removeEventListener(ProgressEvent.PROGRESS,onProgress);
			info.removeEventListener(IOErrorEvent.IO_ERROR,onError);
			info.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onError);
		}
		
		/** 加载事件 */
		private function onComplete(e:ClassLoadCompleteEvent):void 
		{
			var info:LoaderInfo = e.currentTarget as LoaderInfo;
			RemoveLoadEvent(info);
			this.dispatchEvent(e);
			trace("加载完成")
		}
		
		/** 加载中 */
		private function onProgress(e:ProgressEvent):void 
		{
			this.dispatchEvent(e);
		}
		
		/** 出错事件 */
		private function onError(e:Event):void 
		{
			this.dispatchEvent(e);
		}
	}
}